package ru.reaperoq.routing

import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.auth.*
import io.ktor.server.routing.*
import ru.reaperoq.database.Database
import ru.reaperoq.dto.*
import ru.reaperoq.schema.UserRole
import ru.reaperoq.utils.getBody
import ru.reaperoq.utils.getUser
import ru.reaperoq.utils.withRole

fun Routing.componentsRouting() {
    authenticate {
        get(URLS.Components.COMPONENTS) {
            withRole(UserRole.ADMIN, UserRole.MODERATOR) {
                call.respondSuccess(Database.componentsService.readAll().map { component ->
                    val createdBy = Database.userService.read(component.createdBy) ?: run {
                        call.respondError("Пользователь не найден", HttpStatusCode.NotFound)
                        return@withRole
                    }
                    val verifiedBy = Database.userService.read(component.verifiedBy) ?: run {
                        call.respondError("Пользователь не найден", HttpStatusCode.NotFound)
                        return@withRole
                    }
                    ComponentResponse.from(component, UserResponse.from(createdBy), UserResponse.from(verifiedBy))
                })
            }
        }

        get(URLS.Components.MY) {
            val user = getUser() ?: return@get
            if (user.locationId == null) {
                call.respondError("Пользователь не привязан к локации", HttpStatusCode.BadRequest)
                return@get
            }
            call.respondSuccess(Database.componentsService.readByLocation(user.locationId).map { component ->
                val verifiedBy = Database.userService.read(component.verifiedBy) ?: run {
                    call.respondError("Пользователь не найден", HttpStatusCode.NotFound)
                    return@get
                }
                ComponentResponse.from(component, UserResponse.from(user), UserResponse.from(verifiedBy))
            })
        }

        get(URLS.Components.COMPONENT) {
            withRole(UserRole.ADMIN, UserRole.MODERATOR) {
                val id = call.parameters["id"]?.toIntOrNull() ?: run {
                    call.respondError("Неверный id", HttpStatusCode.BadRequest)
                    return@withRole
                }
                val component = Database.componentsService.read(id) ?: run {
                    call.respondError("Компонент не найден", HttpStatusCode.NotFound)
                    return@withRole
                }
                val createdBy = Database.userService.read(component.createdBy) ?: run {
                    call.respondError("Пользователь не найден", HttpStatusCode.NotFound)
                    return@withRole
                }
                val verifiedBy = Database.userService.read(component.verifiedBy) ?: run {
                    call.respondError("Пользователь не найден", HttpStatusCode.NotFound)
                    return@withRole
                }
                call.respondSuccess(
                    ComponentResponse.from(component, UserResponse.from(createdBy), UserResponse.from(verifiedBy))
                )
            }
        }

        get(URLS.Components.COMPONENT_BY_SERIAL) {
            val serial = call.parameters["serial"] ?: run {
                call.respondError("Не указан серийный номер", HttpStatusCode.BadRequest)
                return@get
            }
            val component = Database.componentsService.readBySerial(serial) ?: run {
                call.respondError("Компонент не найден", HttpStatusCode.NotFound)
                return@get
            }
            val createdBy = Database.userService.read(component.createdBy) ?: run {
                call.respondError("Пользователь не найден", HttpStatusCode.NotFound)
                return@get
            }
            val verifiedBy = Database.userService.read(component.verifiedBy) ?: run {
                call.respondError("Пользователь не найден", HttpStatusCode.NotFound)
                return@get
            }
            call.respondSuccess(
                ComponentResponse.from(component, UserResponse.from(createdBy), UserResponse.from(verifiedBy))
            )
        }

        post(URLS.Components.COMPONENTS) {
            withRole(UserRole.ADMIN, UserRole.MODERATOR) {
                val body = call.getBody<CreateComponentRequest>() ?: return@withRole
                val user = getUser() ?: return@withRole
                val id = Database.componentsService.create(
                    user.id,
                    body.name,
                    body.type,
                    body.specifications,
                    body.purchaseDate,
                    body.computerId,
                    body.locationId,
                    body.serialNumber,
                    user.id
                )
                call.respondSuccess(id)
            }
        }

        put(URLS.Components.COMPONENT) {
            withRole(UserRole.ADMIN, UserRole.MODERATOR) {
                val id = call.parameters["id"]?.toIntOrNull() ?: run {
                    call.respondError("Неверный id", HttpStatusCode.BadRequest)
                    return@withRole
                }
                val body = call.getBody<CreateComponentRequest>() ?: return@withRole
                Database.componentsService.update(
                    id,
                    body.name,
                    body.type,
                    body.specifications,
                    body.purchaseDate,
                    body.computerId,
                    body.locationId
                )
                call.respondSuccess("Компонент обновлен")
            }
        }

        delete(URLS.Components.COMPONENT) {
            withRole(UserRole.ADMIN, UserRole.MODERATOR) {
                val id = call.parameters["id"]?.toIntOrNull() ?: run {
                    call.respondError("Неверный id", HttpStatusCode.BadRequest)
                    return@withRole
                }
                Database.componentsService.delete(id)
                call.respondSuccess("Компонент удален")
            }
        }

        post(URLS.Components.VERIFY) {
            val id = call.parameters["id"]?.toIntOrNull() ?: run {
                call.respondError("Неверный id", HttpStatusCode.BadRequest)
                return@post
            }
            val user = getUser() ?: return@post
            Database.componentsService.verify(id, user.id)
            call.respondSuccess("Компонент подтвержден")
        }

        get(URLS.Components.COMPONENTS_BY_COMPUTER) {
            withRole(UserRole.ADMIN, UserRole.MODERATOR) {
                val id = call.parameters["id"]?.toIntOrNull() ?: run {
                    call.respondError("Неверный id", HttpStatusCode.BadRequest)
                    return@withRole
                }
                val components = Database.componentsService.readByComputer(id)
                call.respondSuccess(components.map { component ->
                    val createdBy = Database.userService.read(component.createdBy) ?: run {
                        call.respondError("Пользователь не найден", HttpStatusCode.NotFound)
                        return@withRole
                    }
                    val verifiedBy = Database.userService.read(component.verifiedBy) ?: run {
                        call.respondError("Пользователь не найден", HttpStatusCode.NotFound)
                        return@withRole
                    }
                    ComponentResponse.from(component, UserResponse.from(createdBy), UserResponse.from(verifiedBy))
                })
            }
        }

        get(URLS.Components.COMPONENTS_BY_LOCATION) {
            withRole(UserRole.ADMIN, UserRole.MODERATOR) {
                val id = call.parameters["id"]?.toIntOrNull() ?: run {
                    call.respondError("Неверный id", HttpStatusCode.BadRequest)
                    return@withRole
                }
                call.respondSuccess(Database.componentsService.readByLocation(id))
            }
        }

        get(URLS.Components.TYPES) {
            call.respondSuccess(Database.componentsService.readTypes())
        }
    }
}